#ifndef __USBHOST_H__
#define __USBHOST_H__

#include "usbdescriptors.h"

#ifdef  __USB_GLONALS__
#define _USB_EXT
#else
#define _USB_EXT extern
#endif // __USB_GLONALS__


//#define USBIntrSource				(57)


// USB Standard Request Define
#define GET_STATUS 			1
#define CLEAR_FEATURE 		2
#define SET_FEATURE 		3
#define SET_ADDRESS 		4
#define GET_DESCRIPTOR 		5
#define SET_DESCRIPTOR 		6
#define GET_CONFIGURATION 	7
#define SET_CONFIGURATION 	8
#define GET_INTERFACE 		9
#define SET_INTERFACE 		10
#define SYNCH_FRAME 		11

#define intrUSB_Suspend_MSK				(0x01)
#define intrUSB_Suspend_OFST			(0)
#define intrUSB_Resume_MSK				(0x02)
#define intrUSB_Resume_OFST				(1)
#define intrUSB_Reset_Babble_MSK		(0x04)
#define intrUSB_Reset_Babble_OFST		(2)
#define intrUSB_Discon_MSK				(0x20)
#define intrUSB_Discon_OFST				(5)
#define intrUSB_VBusError_MSK			(0x80)
#define intrUSB_VBusError_OFST			(7)
/**	intrTx Reg MSK Definition	**/
#define intrTx_EP0_MSK					(0x01)
#define intrTx_EP0_OFST					(0)
#define intrTx_EP1_MSK					(0x02)
#define intrTx_EP1_OFST					(1)
#define intrRx_EP1_MSK					(0x02)
#define intrRx_EP1_OFST					(1)

#define EP0 0
#define EP1 1
#define EP2 2

//--------------------------------------STM32------------------------------------//
#define  USB_DESC_TYPE_DEVICE                              1
#define  USB_DESC_TYPE_CONFIGURATION                       2
#define  USB_DESC_TYPE_STRING                              3
#define  USB_DESC_TYPE_INTERFACE                           4
#define  USB_DESC_TYPE_ENDPOINT                            5
#define  USB_DESC_TYPE_DEVICE_QUALIFIER                    6
#define  USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION           7
#define  USB_DESC_TYPE_INTERFACE_POWER                     8
#define  USB_DESC_TYPE_HID_REPORT                          0x22

#define  USB_DESC_DEVICE                    ((USB_DESC_TYPE_DEVICE << 8) & 0xFF00)
#define  USB_DESC_CONFIGURATION             ((USB_DESC_TYPE_CONFIGURATION << 8) & 0xFF00)
#define  USB_DESC_STRING                    ((USB_DESC_TYPE_STRING << 8) & 0xFF00)
#define  USB_DESC_INTERFACE                 ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00)
#define  USB_DESC_ENDPOINT                  ((USB_DESC_TYPE_INTERFACE << 8) & 0xFF00)
#define  USB_DESC_DEVICE_QUALIFIER          ((USB_DESC_TYPE_DEVICE_QUALIFIER << 8) & 0xFF00)
#define  USB_DESC_OTHER_SPEED_CONFIGURATION ((USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION << 8) & 0xFF00)
#define  USB_DESC_INTERFACE_POWER           ((USB_DESC_TYPE_INTERFACE_POWER << 8) & 0xFF00)
#define  USB_DESC_HID_REPORT                ((USB_DESC_TYPE_HID_REPORT << 8) & 0xFF00)



typedef struct _USB_CONFIGURE_DESCRIPTOR
{
	uint8_t bLength0;
	uint8_t bDescriptorType0;
	uint8_t wTotalLengthH;
	uint8_t wTotalLengthL;
	uint8_t BNumInterfaces;
	uint8_t bConfigurationValue;
	uint8_t iCongfiguration;
	uint8_t bmAttribute;
	uint8_t MaxPower;

	uint8_t bLength1;
	uint8_t bDescriptorType1;
	uint8_t bInterfaceNumber;
	uint8_t bAlternateSetting;
	uint8_t bNumberEndpoints;
	uint8_t bInterfaceClass;
	uint8_t bInterfaceSubClass;
	uint8_t bInterfaceProtocol;
	uint8_t iInterface;

	uint8_t bLengthep1;
	uint8_t bDescriptorTypeep1;
	uint8_t bEndpointAddressep1;
	uint8_t bmAttributesep1;
	uint8_t wMaxPacketSizeep1L;
	uint8_t wMaxPacketSizeep1H;
	uint8_t bIntervalep1;	

	uint8_t bLengthep2;
	uint8_t bDescriptorTypeep2;
	uint8_t bEndpointAddressep2;
	uint8_t bmAttributesep2;
	uint8_t wMaxPacketSizeep2L;
	uint8_t wMaxPacketSizeep2H;
	uint8_t bIntervalep2;	

	uint8_t config1;
	uint8_t config2;
	uint8_t config3;
	uint8_t config4;
	uint8_t config5;
	uint8_t config6;
	uint8_t config7;	
	uint8_t config8;
	uint8_t config9;
} USB_CONFIGURE_DESCRIPTOR;



/*---------------------------------STM32 Routine---------------------------------*/
#define FUNCTION_DOING    0
#define FUNCTION_OK       1
#define FUNCTION_NOWORK   2
#define FUNCTION_ERROR    3
#define FUNCTION_STOP     4

#define USB_ADDRESS       2

#define GETDESCRIPTORE   0x8006
#define SETCONFIGURE     0x0009
#define SETADDRESSE      0x0005
#define SETINTERFACE     0x010b

#define DEV_DESC      0x0100
#define CFG_DESC      0x0200
#define STR_DESC      0x0300
#define INT_DESC      0x0400
#define END_DESC      0x0500

#define CBW_CB_LENGTH    16
#define CBW_TOTALLENGTH    31

#define OPCODE_TEST_UNIT_READY            0x00
#define OPCODE_READ_CAPACITY10            0x25
#define OPCODE_MODE_SENSE6                0x1A
#define OPCODE_READ10                     0x28
#define OPCODE_WRITE10                    0x2A
#define OPCODE_REQUEST_SENSE              0x03
#define OPCODE_INQUIRY		              0x12
#define OPCODE_READ_FORMATC		          0x23

typedef union
{
	uint16_t w;
	struct BW
	{
		uint8_t msb;
		uint8_t lsb;
	}bw;
}uint16_t_uint8_t;

/* Following states are used for gState */
typedef enum
{
	HOST_IDLE = 0,
	HOST_ISSUE_CORE_RESET,
	HOST_DEV_ATTACHED,
	HOST_DEV_DISCONNECTED,  
	HOST_ISSUE_RESET,
	HOST_DETECT_DEVICE_SPEED,
	HOST_ENUMERATION,
	HOST_CLASS_REQUEST,  
	HOST_CLASS,
	HOST_CTRL_XFER,
	HOST_USR_INPUT,
	HOST_SUSPENDED,
	HOST_ERROR_STATE,
	HOST_NONE
}HOST_STATE;  

/* Following states are used for EnumerationState */
typedef enum
{
	ENUM_IDLE = 0,
	ENUM_GET_FULL_DEV_DESC,
	ENUM_SET_ADDR,
	ENUM_GET_CFG_DESC,
	ENUM_GET_FULL_CFG_DESC,
	ENUM_GET_STRING_LANGUAGE,
	ENUM_GET_MFC_STRING_DESC,
	ENUM_GET_PRODUCT_STRING_DESC,
	ENUM_GET_SERIALNUM_STRING_DESC,
	ENUM_SET_CONFIGURATION,
	ENUM_GET_MAXLUN,
	ENUM_SET_INTERFACE,
	ENUM_DEV_CONFIGURED,
	ENUM_COMPLETED,
	ENUM_XFER,
	ENUM_RESET,
	ENUM_NONE
}ENUM_STATE;  

typedef enum
{
	MSC_BOT_INIT_STATE = 0,                
	MSC_BOT_RESET,                
	MSC_GET_MAX_LUN,  
	MSC_TEST_UNIT_READY,
	MSC_INQUIRY,  
	MSC_READ_FORMATC,
	MSC_READ_CAPACITY10,
	MSC_MODE_SENSE6,
	MSC_REQUEST_SENSE,            
	MSC_BOT_USB_TRANSFERS,        
	MSC_DEFAULT_APPLI_STATE,  
	MSC_CTRL_XFER,
	MSC_BOT_XFER,
	MSC_CTRL_ERROR_STATE,
	MSC_UNRECOVERED_STATE,
	MSC_NONE
}MSC_STATE;

/* Following states are used for CtrlXferStateMachine */
typedef enum
{
	CTRL_IDLE = 0,
	CTRL_SETUP,
	CTRL_DATA_IN,
	CTRL_DATA_OUT,
	CTRL_STATUS_IN,
	CTRL_STATUS_OUT,
	CTRL_ERROR,
	CTRL_NONE
}CTRL_XFER_STATE;  

typedef enum
{
	RESPON_START = 0,
	RESPON_OK,
	RESPON_TEST,
	RESPON_ACK,
	RESPON_HALTED,
	RESPON_NAK,
	RESPON_ERROR,
	RESPON_STALL,
	RESPON_FAIL,
	RESPON_NONE
}CTRL_RESP_STATE;

typedef enum
{
	BOT_IDLE = 0,
	BOT_DATA_IN,
	BOT_CSW_IN,
	BOT_DATA_OUT,
	BOT_DATA_DEAL,
	BOT_FAT_CBW,
	BOT_FAT_IN,
	BOT_FAT_OUT,
	BOT_FAT_CSW,
	BOT_FAT_DEAL,
	BOT_DATA_INLAST,
	BOT_CSW_SEND,
	BOT_ERROR,
	BOT_NONE
}MSC_XFER_STATE;  

typedef enum
{
	REBOT_START = 0,
	REBOT_OK,
	REBOT_TEST,
	REBOT_ACK,
	REBOT_HALTED,
	REBOT_NAK,
	REBOT_ERROR,
	REBOT_STALL,
	REBOT_FAIL,
	REBOT_NONE
}MSC_RESP_STATE;

typedef struct _USB_Setup
{
	uint8_t	RequestType;
	uint8_t	Request;
	uint8_t	ValueL;
	uint8_t	ValueH;
	uint8_t	IndexL;
	uint8_t	IndexH;
	uint8_t	LengthL;
	uint8_t	LengthH;
	uint16_t	Datalength;
	uint8_t	Data[64];
}USB_STANDREQ;  

typedef struct _USB_MSCCBW
{
	uint32_t	CBWSignature;
	uint32_t	CBWTag;
	uint32_t	CBWTransferLength;
	uint8_t	CBWFlags;
	uint8_t	CBWLUN; 
	uint8_t	CBWLength;
	uint8_t	CBWCB[16];
	uint16_t	Datalength;
}USB_MSCCBWREQ;

#if 0
typedef struct _USB_INFO
{
	USB_DEVICE_DESCRIPTOR DeviceDes;
	USB_CONFIGURE_DESCRIPTOR ConfigureDes;
	uint8_t	StringDes[64];
	uint8_t	MSCmaxlun;
	uint8_t	INendnum;
	uint8_t	OUTendnum;
	uint16_t	INendsize;
    uint16_t	OUTendsize;
	uint8_t	BOTInquiry[36];
	uint8_t	BOTCapacity[8];
	uint8_t	BOTSense6[12];
	uint8_t	BOTSense[12];
	uint8_t	BOTformatc[24];
}USB_INFO; 
#endif

typedef struct _Process
{
	HOST_STATE			gState;        /*  Host State Machine Value */
	ENUM_STATE			EnumStateBkp;  /* backup of previous State machine value */
	ENUM_STATE			EnumState;     /* Enumeration state Machine */  
	CTRL_XFER_STATE     CtrlXfer;
	CTRL_RESP_STATE     CtrlResp;
	MSC_STATE			MSCStateBkp;
	MSC_STATE           MSCState;
	MSC_XFER_STATE      BOTXfer;
	MSC_RESP_STATE      BOTResp;
}USBH_MACHINE;

typedef struct _FAT_INFO
{
	uint16_t	sendremain;
	uint16_t	readremain;
	uint8_t*	sendfifo;
	uint8_t*	readfifo;
	uint16_t	readcnt;
	uint16_t	sendcnt;
}FAT_INFO;


uint8_t USB_FS_Init(void);
int UsbHostInit(char* p);
void EnableUsbInt(void);
void DisableUsbInt(void);
uint8_t USBEpxTransmit(uint8_t epx, uint16_t epxlen, uint8_t* buf, uint16_t len);  /* USB send data to epx endpoint with buf and buf len */ 

void ConnectRoutine(USBH_MACHINE* inUSBH_Machine);
void DisconnectRoutine(USBH_MACHINE* inUSBH_Machine);
void ResetRoutine(USBH_MACHINE* inUSBH_Machine);

//uint8_t USBEp0Routine(USBH_MACHINE* inUSBH_Machine, USB_STANDREQ* inUSB_Standreq,
//					USB_INFO* inUSBinfo);
//void USBTxEpRoutine(USBH_MACHINE* inUSBH_Machine, USB_INFO* inUSBinfo,USB_MSCCBWREQ* inUSB_MSCCWBreq);
//void USBRxEpRoutine(USBH_MACHINE* inUSBH_Machine,USB_INFO* inUSBinfo, USB_MSCCBWREQ* inUSB_MSCCWBreq, uint8_t* buf);

/* ONLY USED IN DEVICE MODE */
/* ONLY USED IN HOST MODE */
void USB_Send_SETUP(uint8_t* buf);
void USB_Send_IN(void);
void USB_Send_OUT(uint8_t* buf,uint16_t length);

void USBH_Process(void);
void USB_Reset_Targetdevice(void);
uint8_t USBH_HandleEnum(void);
uint8_t USBH_HandleMSC(void);
//uint8_t InitBulkEndx(USB_INFO *inUSBinfo);

uint8_t USBH_MSC_HandleBOTXfer(USB_MSCCBWREQ* inmsccbwreq);
uint8_t USBH_MSC_Read10(uint8_t* buf, uint32_t address, uint32_t length);
uint8_t USBH_MSC_Write10(uint8_t* buf, uint32_t address, uint32_t length);
void USBH_ENUMDescriptor(USB_STANDREQ* standreq,uint16_t request, 
						 uint16_t reqvalue,uint16_t reqindex, uint16_t reqlength);
						 
#endif // __USBCTRL_H__

